// /////////////////////////////////////////////////////////////////////////////
//
// Name:            AnimatedMeshComponent.h
// Author:          Michael Bartsch (ZCCdark203)
//
// Desc :           Declaration of the AnimatedMeshComponent class.
//
// License:         Copyright (C) 2009 Michael Bartsch and Contributors
//
//                  This program is free software: you can redistribute it
//                  and/or modify it under the terms of the zlib/libpng License.
//                  See main.cpp for conditions of distribution and use.
//
// /////////////////////////////////////////////////////////////////////////////

#ifndef __ANIMATEDMESHCOMPONENT_H__
#define __ANIMATEDMESHCOMPONENT_H__

// Include files
#include "../../dependencies.h"
#include "SceneComponent.h"


// AnimatedMeshComponent class
//! Component wrapper of Irrlicht's IAnimatedMeshSceneNode.
//!
//! <b>XML:</b>
//! \code
//! <AnimatedMeshComponent>
//!    <!-- Properties -->
//! </AnimatedMeshComponent>
//! \endcode
class AnimatedMeshComponent : public SceneComponent
{
public:

    // Initialisation and deinitialisation
    //! Constructor (default)
    //! @param parent        The parent entity to which the component should be added.
    AnimatedMeshComponent(Entity *parent);
    //! Constructor
    //! @param parent        The parent entity to which the component should be added.
    //! @param fileName      Filename of the mesh to load.
    //! @param scale         Initial scale of the mesh.
    AnimatedMeshComponent(Entity *parent, const std::string &fileName,
                          const vector3df &scale = vector3df(1.0f, 1.0f, 1.0f));
    //! Constructor
    //! @param parent        The parent entity to which the component should be added.
    //! @param mesh          Pointer to the loaded animated mesh to be displayed.
    //! @param scale         Initial scale of the mesh.
    //! @note Not available in AngelScript.
    AnimatedMeshComponent(Entity *parent, IAnimatedMesh *mesh,
                          const vector3df &scale = vector3df(1.0f, 1.0f, 1.0f));
    //! Deconstructor
    ~AnimatedMeshComponent();

    // Methods
    //! Returns a direct pointer to the IAnimatedMeshSceneNode.
    //! @note Not available in AngelScript.
    IAnimatedMeshSceneNode* getAnimatedMeshSceneNode();

    //! Animates the mesh based upon the current frame.
    void animate();

    //! Returns the current end frame number.
    s32 getEndFrame() const;
    //! Returns the current displayed frame number.
    f32 getFrame() const;
    //! Returns the current mesh.
    //! @note Not available in AngelScript.
    IMesh* getMesh();
    //! Gets the IShadowVolumeSceneNode associated with this component.
    //! @note Not available in AngelScript.
    IShadowVolumeSceneNode* getShadowVolumeSceneNode();
    //! Returns the current start frame number.
    s32 getStartFrame() const;

    //! Sets the speed (in frames/s) with which the animation is played.
    //!
    //! <b>XML:</b>
    //! \code
    //! <animationSpeed value="" />
    //! \endcode
    //!
    //! @param speed         Frames per second played.
    void setAnimationSpeed(f32 speed);
    //! Sets the current frame number.
    //!
    //! <b>XML:</b>
    //! \code
    //! <currentFrame value="" />
    //! \endcode
    //!
    //! @param frame         Number of the frame to let the animation be started from.
    void setCurrentFrame(f32 frame);
    //! Sets the frame numbers between which the animation is looped.
    //!
    //! <b>XML:</b>
    //! \code
    //! <frameLoop start="" end="" />
    //! \endcode
    //!
    //! @param start         Start frame number of the loop.
    //! @param end           End frame number of the loop.
    void setFrameLoop(s32 start, s32 end);
    //! Sets looping mode which is on by default.
    //!
    //! <b>XML:</b>
    //! \code
    //! <loopMode value="" />
    //! \endcode
    //!
    //! @param value         The value of this option.
    void setLoopMode(bool value);
    //! Starts a MD2 animation.
    //!
    //! <b>XML:</b>
    //! \code
    //! <MD2Animation value="" />
    //! \endcode
    //!
    //! @param animationName Name of the animation which should be played.
    void setMD2Animation(const std::string &animationName);
    //! Starts a MD2 animation.
    //! @param anim          An MD2 animation type, which should be played.
    //!                      (see: Irrlicht API documentation)
    //! @note Not available in AngelScript.
    void setMD2Animation(EMD2_ANIMATION_TYPE anim);
    //! Loads and sets a new mesh to display.
    //!
    //! <b>XML:</b>
    //! \code
    //! <mesh fileName="" />
    //! \endcode
    //!
    //! fileName             Filename of the mesh to load.
    void setMesh(const std::string &fileName);
    //! Sets a new mesh to display.
    //! @param mesh          Pointer to the loaded animated mesh to be displayed.
    //! @note Not available in AngelScript.
    void setMesh(IAnimatedMesh *mesh);
    //! Sets the mesh of the IShadowVolumeSceneNode attached to this component.
    //! @param fileName      Filename of the mesh to load.
    //! @note You must first call setShadowVolumeSceneNode!
    void setShadowVolumeMesh(const std::string &fileName);
    //! Sets the mesh of the IShadowVolumeSceneNode attached to this component.
    //! @param mesh          Pointer to the loaded mesh to be used.
    //! @note You must first call setShadowVolumeSceneNode!
    void setShadowVolumeMesh(IMesh *mesh);
    //! Loads and sets a new IShadowVolumeSceneNode to the component.
    //!
    //! <b>XML:</b>
    //! \code
    //! <shadowVolumeMeshSceneNode fileName="" zfailmethod="" infinity="" />
    //! \endcode
    //!
    //! @param fileName      Filename of the mesh to load.
    //! @param zfailmethod   If set to true, the shadow will use the zfail method, if not,
    //!                      zpass is used.
    //! @param infinity      Value used by the shadow volume algorithm to scale the shadow volume.
    void setShadowVolumeSceneNode(const std::string &fileName, bool zfailmethod = true,
                                  f32 infinity = 10000.0f);
    //! Adds a new IShadowVolumeSceneNode to the component.
    //! @param mesh          Pointer to the loaded mesh to be used.
    //! @param zfailmethod   If set to true, the shadow will use the zfail method, if not,
    //!                      zpass is used.
    //! @param infinity      Value used by the shadow volume algorithm to scale the shadow volume.
    //! @note Not available in AngelScript.
    void setShadowVolumeSceneNode(IMesh *mesh, bool zfailmethod = true,
                                  f32 infinity = 10000.0f);
    //! Sets the transition time in seconds.
    //!
    //! <b>XML:</b>
    //! \code
    //! <transitionTime value="" />
    //! \endcode
    //!
    //! @param time          Transition time in seconds.
    void setTransitionTime(f32 time);

    // Events
    //! Responds to changes of the mesh attached to this component.
    //! @note For internal use only!
    void onMesh(void *p);
    //! Responds to changes of the mesh attached to the shadow volume scene node of this component.
    //! @note For internal use only!
    void onShadowVolumeMesh(void *p);

    // XML
    //! Parses for a AnimatedMeshComponent.
    //! @note For internal use only!
    static bool parseXML(IXMLReader *file, Entity *entity);

private:

    // Private methods.
    //! Common initialisation method.
    void init(const vector3df &scale = vector3df(1.0f, 1.0f, 1.0f));

    // Members
    IAnimatedMeshSceneNode *mAnimatedMeshSN;
    IShadowVolumeSceneNode *mShadowVolumeSN;

    std::string mMeshFileName;
    std::string mShadowVolumeMeshFileName;
};

#endif
